package imse.team0.processors;

import imse.team0.orderws.InvalidRequest;
import imse.team0.orderws.data.InvalidationReasonType;
import imse.team0.orderws.data.OrderType;
import imse.team0.orderws.data.ReceiptAcknowledgmentType;
import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.cxf.message.MessageContentsList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sun.misc.BASE64Encoder;

import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;

/**
 * @author Eugen, 4/26/12 5:26 PM
 */
public class OrderItemIDValidator {

    private static Map<String, Message> orderRequestStore = new HashMap<String, Message>(1);
    private static final String NL = System.getProperty("line.separator");
    private static final AtomicLong uniqueID = new AtomicLong(0);
    private static final Logger RESULT_LOGGER = LoggerFactory.getLogger("imse.team0.results");

    public void buildIDList(Exchange exchange) {
        OrderType order = (OrderType) ((MessageContentsList) exchange.getIn().getBody()).get(0);
        SimpleDateFormat sdf = new SimpleDateFormat("[HH:mm:ss.SSS]");
        Date date = new Date(Long.parseLong("" + order.getTimestamp()));
        RESULT_LOGGER.info("--Received SOAP Request: clientID="+order.getClientID()+", time="+sdf.format(date)+"--");
        String key = ""+uniqueID.incrementAndGet();
        BASE64Encoder encoder = new BASE64Encoder();
        key = encoder.encode(key.getBytes());
        Message msg = orderRequestStore.put(key, exchange.getIn());
        exchange.getOut().setHeader("claimCheck", key);
        String itemList = "";
        for (OrderType.OrderItem item : order.getOrderItem()) {
            itemList += item.getId() + ",";
        }
        itemList = itemList.substring(0, itemList.length()-1);
        exchange.getOut().setBody(itemList+NL);
    }

    public void createValidationReply(Exchange exchange) throws InvalidRequest{
        Message in = exchange.getIn();
        String reply = (String) in.getBody();
        Message originalOrderRequestMessage = orderRequestStore.remove(in.getHeader("claimCheck"));
        if (reply.startsWith("INVALID"))
        {
            InvalidationReasonType errorReply  = new InvalidationReasonType();
            errorReply.setReceivedOrder((OrderType) originalOrderRequestMessage.getBody(List.class).get(0));
            List<InvalidationReasonType.InvalidOrderItem> invalidItems = errorReply.getInvalidOrderItem();
            String[] items = reply.split(":");
            items = items[1].split(",");
            for (String item : items)
            {
                InvalidationReasonType.InvalidOrderItem orderItem = new InvalidationReasonType.InvalidOrderItem();
                orderItem.setErrorCode(404);
                orderItem.setOrderItemID(item);
                orderItem.setText("Order Item with ID="+item+" was not found in the catalog.");
                invalidItems.add(orderItem);
            }
            InvalidRequest exception = new InvalidRequest("Invalid order request", errorReply);
            //in.setBody(exception);
            //in.setHeader("Status", "INVALID");
            throw exception;
        }
        else{
            exchange.setIn(originalOrderRequestMessage);
        }
    }

    public void buildAcknowledgeMessage (Exchange exchange){
        OrderType order = (OrderType) exchange.getIn().getBody(List.class).get(0);
        ReceiptAcknowledgmentType okReply = new ReceiptAcknowledgmentType();
        okReply.setCode(200);
        okReply.setText("Order with correlation: <ClientID="+order.getClientID()+";TimeStamp="+order.getTimestamp()+";> received.");
        try {
            okReply.setReceiptTime(DatatypeFactory.newInstance().newXMLGregorianCalendar(new GregorianCalendar()));
        } catch (DatatypeConfigurationException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
        exchange.getIn().setBody(okReply);
    }
}
